/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_lpuart_edma.h"
#if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT
#include "fsl_dmamux.h"
#endif


#include "uart_task.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/




/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/* LPUART user callback */
static uint32_t GetRingBufferLengthDMA(void);
void uart_sendDMA();

/*******************************************************************************
 * Variables
 ******************************************************************************/

lpuart_edma_handle_t g_lpuartEdmaHandle;

#if UART_TX_DMA
edma_handle_t g_lpuartTxEdmaHandle;
AT_NONCACHEABLE_SECTION_INIT(TxBuffer g_txBuffer) = {0};
lpuart_transfer_t sendXfer;
#else
TxBuffer g_txBuffer;
#endif


#if UART_RX_DMA
edma_handle_t g_lpuartRxEdmaHandle;
AT_NONCACHEABLE_SECTION_INIT(RxBuffer g_rxBuffer) = {0};
lpuart_transfer_t receiveXfer;
#else
RxBuffer g_rxBuffer;
#endif

TxBuffer g_MQTTTxBuffer;
RxBuffer g_MQTTRxBuffer;
//uint8_t g_UartReceivedFlag = 0;


/*******************************************************************************
 * Code
 ******************************************************************************/

void uart_sendDMA(uint32_t len)
{
    /* Send g_tipString out. */
    sendXfer.data     = &g_txBuffer.byData[0];
	if(len < RS232_MAX_BUFFER)
	{
		sendXfer.dataSize = len;
	}
	else
	{
		sendXfer.dataSize = RS232_MAX_BUFFER;
	}
    g_lpuartEdmaHandle.txState = kStatus_LPUART_TxIdle;
    LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &sendXfer);

}

void uart_receiveDMA()
{
	LPUART_TransferAbortReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle);
	memset((void *)&g_rxBuffer, 0, sizeof(g_rxBuffer));
	receiveXfer.data  = &g_rxBuffer.byData[0];
	receiveXfer.dataSize = RS232_MAX_BUFFER;
	
	LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);
}


/*!
 * @brief Main function
 */
int uart_init(void)
{
    lpuart_config_t lpuartConfig;
    edma_config_t config;

    /* Initialize the LPUART. */
    /*
     * lpuartConfig.baudRate_Bps = 115200U;
     * lpuartConfig.parityMode = kLPUART_ParityDisabled;
     * lpuartConfig.stopBitCount = kLPUART_OneStopBit;
     * lpuartConfig.txFifoWatermark = 0;
     * lpuartConfig.rxFifoWatermark = 0;
     * lpuartConfig.enableTx = false;
     * lpuartConfig.enableRx = false;
     */
    LPUART_GetDefaultConfig(&lpuartConfig);
    lpuartConfig.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
    lpuartConfig.enableTx     = true;
    lpuartConfig.enableRx     = true;

	lpuartConfig.rxIdleType = kLPUART_IdleTypeStopBit;
	lpuartConfig.rxIdleConfig = kLPUART_IdleCharacter4;

    LPUART_Init(DEMO_LPUART, &lpuartConfig, DEMO_LPUART_CLK_FREQ);

	LPUART_EnableInterrupts(DEMO_LPUART, kLPUART_RxOverrunInterruptEnable
	| kLPUART_NoiseErrorInterruptEnable | kLPUART_IdleLineInterruptEnable
	| kLPUART_FramingErrorInterruptEnable | kLPUART_ParityErrorInterruptEnable);

	EnableIRQ(DEMO_UART_IRQn);

    /* Init DMAMUX */
    DMAMUX_Init(EXAMPLE_LPUART_DMAMUX_BASEADDR);
    /* Set channel for LPUART */
	#if UART_TX_DMA
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL, LPUART_TX_DMA_REQUEST);
	DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL);
	#endif

	#if UART_RX_DMA
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL, LPUART_RX_DMA_REQUEST);
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL);
	#endif

    /* Init the EDMA module */
    EDMA_GetDefaultConfig(&config);
    EDMA_Init(EXAMPLE_LPUART_DMA_BASEADDR, &config);
	#if UART_TX_DMA
    EDMA_CreateHandle(&g_lpuartTxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL);
	#endif

	#if UART_RX_DMA
	EDMA_CreateHandle(&g_lpuartRxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL);
    /* Create LPUART DMA handle. */
    LPUART_TransferCreateHandleEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, NULL, NULL, &g_lpuartTxEdmaHandle,
                                    &g_lpuartRxEdmaHandle);	
	#else
    /* Create LPUART DMA handle. */
    LPUART_TransferCreateHandleEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, NULL, NULL, &g_lpuartTxEdmaHandle,
                                    NULL);
	#endif

	//Start to received UART
	uart_receiveDMA();

	#if 0
	while(1)
	{
		if(g_rxBuffer.flag == 1)
		{
			uart_sendDMA(g_txBuffer.uCount);
			g_rxBuffer.flag= 0;
		}
	}
	#endif

}



/* GPS LPUART user callback */
void LPUART_RX_ISR()
{
	//uint8_t data = 0;
	uint32_t status = 0;
	//static uint32_t last_time = 0;
	//uint32_t current_time = 0;

	status = LPUART_GetStatusFlags(DEMO_LPUART);

	if ((kLPUART_IdleLineFlag) & status)
	{
		LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_IdleLineFlag);
		g_rxBuffer.uCount = GetRingBufferLengthDMA();
		memcpy((void *)&g_MQTTTxBuffer.byData[0], (void *)&g_rxBuffer.byData, g_rxBuffer.uCount);
		g_MQTTTxBuffer.uCount = g_rxBuffer.uCount;
		//Continue to receive the next frame
		uart_receiveDMA();
		g_rxBuffer.flag = 1;

	}

	if ((kLPUART_LinBreakInterruptEnable|kLPUART_RxOverrunInterruptEnable
	| kLPUART_NoiseErrorInterruptEnable | kLPUART_FramingErrorInterruptEnable 
	| kLPUART_ParityErrorInterruptEnable) & status)
	{
		LPUART_ClearStatusFlags(DEMO_LPUART, kLPUART_LinBreakInterruptEnable
	|kLPUART_RxOverrunInterruptEnable | kLPUART_NoiseErrorInterruptEnable
	| kLPUART_FramingErrorInterruptEnable | kLPUART_ParityErrorInterruptEnable);
	}
		
	SDK_ISR_EXIT_BARRIER;
}


static uint32_t GetRingBufferLengthDMA(void)
{
	return (RS232_MAX_BUFFER - EDMA_GetRemainingMajorLoopCount(EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL));
}


